package pl.diagnoser.server.lpr;

import java.util.ArrayList;
import java.util.List;
import java.util.Collections;

import pl.diagnoser.client.dto.DefectDictDTO;
import pl.diagnoser.client.dto.DiagnoserResultDTO;
import pl.diagnoser.client.dto.ObjectsDTO;
import pl.diagnoser.client.dto.SymptomDTO;
import pl.diagnoser.client.tools.SearchObjectAttribute;
import pl.diagnoser.server.persistance.dao.ObjectsDao;
import pl.diagnoser.server.persistance.map.Objects;
import lprlibrary.formula.V;
import lprlibrary.lpr.Engine;
import lprlibrary.lpr.KnowledgeBase;
import lprlibrary.lpr.Vertex;
import lprlibrary.rule.MLRule;

public class DiagnoserEngine extends Engine {
	
	public DiagnoserEngine(KnowledgeBase knowledgeBase) {
		super(knowledgeBase);
	}
	
	public List<DefectDictDTO> getPossibleDefects(ObjectsDTO object, List<SymptomDTO> symptoms) {
        List<DefectDictDTO> possibleDefects = new ArrayList<DefectDictDTO>();
        
        for (SymptomDTO symptom : symptoms) {
                V formulaV = new V(DiagnoserKnowledgeBase.OBJECTS, DiagnoserKnowledgeBase.HAS, symptom.getSymptomName());
                formulaV.setConfidence(symptom.getSymptomConfidence());
                knowledgeBase.addFormula(formulaV);
        }
        
        for (String illness : ((DiagnoserKnowledgeBase) knowledgeBase).getDefectsList(false)) {
                V query = new V(DiagnoserKnowledgeBase.USER, DiagnoserKnowledgeBase.DEFECT_WITH, illness);
                
                if (doIterativeDeepSearch(query)) {
                        possibleDefects.add(new DefectDictDTO(illness, query.getConfidence()));
                }
        }

        Collections.sort(possibleDefects);
        Collections.reverse(possibleDefects);
        return possibleDefects;
	}
	
	public List<DiagnoserResultDTO> getPossibleDefects(List<SearchObjectAttribute> searchCriteria, List<SearchObjectAttribute> emptySearchCriteria, boolean fast) {
		List<DiagnoserResultDTO> possibleDefects = new ArrayList<DiagnoserResultDTO>();
		
		
		//Najpierw iterujemy po wpisanych atrybutach
		for(SearchObjectAttribute searchObjectAttribute : searchCriteria) {
			
			if(searchObjectAttribute.isSingle()) {
				V formulaV = new V(DiagnoserKnowledgeBase.USER, DiagnoserKnowledgeBase.CHOSEN + " " + searchObjectAttribute.getAttributeName().replace("_", " "), searchObjectAttribute.getSingleValue(true));
				System.out.println("1: " + formulaV.toString());
				formulaV.setConfidence(searchObjectAttribute.getConfidence());
				knowledgeBase.addFormula(formulaV);
			} else
			{
				V formulaV = new V(DiagnoserKnowledgeBase.USER, DiagnoserKnowledgeBase.CHOSEN + " " + searchObjectAttribute.getAttributeName().replace("_", " "), searchObjectAttribute.getAttributeValues(true));
				System.out.println("2: " + formulaV.toString());
				formulaV.setConfidence(searchObjectAttribute.getConfidence());
				knowledgeBase.addFormula(formulaV);
			}
		}
		/*
		//...a nastepnie po pustych - uzupełnionych całym słownikiem z bazy
		for(final SearchObjectAttribute searchObjectAttribute : emptySearchCriteria) {
			searchObjectAttribute.setAttributeValues(new AttributeDictDao().getAttributeValues(searchObjectAttribute.getAttributeName()));
			
			if(searchObjectAttribute.isSingle()) {
				V formulaV = new V(DiagnoserKnowledgeBase.INNOVATION, searchObjectAttribute.getAttributeName().replace("_", " "), searchObjectAttribute.getSingleValue());
				System.out.println("3: " + formulaV.toString());
				formulaV.setConfidence(searchObjectAttribute.getConfidence());
				knowledgeBase.addFormula(formulaV);
			} else
			{
				V formulaV = new V(DiagnoserKnowledgeBase.INNOVATION, searchObjectAttribute.getAttributeName().replace("_", " "), searchObjectAttribute.getAttributeValues());
				System.out.println("4: " + formulaV.toString());
				formulaV.setConfidence(searchObjectAttribute.getConfidence());
				knowledgeBase.addFormula(formulaV);
			}
		}
		*/
		
		for (String defects : ((DiagnoserKnowledgeBase) knowledgeBase).getDefectsList(true)) {

			
			Boolean isFound = false;
			Integer counter = 0;
			Float confidence = new Float(0);
			for(SearchObjectAttribute searchObjectAttribute : searchCriteria) {
				counter++;
				

				if(searchObjectAttribute.isSingle()) {
					
					V query3 = null;
					
					if (fast) {
						query3 = new V(defects, searchObjectAttribute.getAttributeName().replace("_", " "), searchObjectAttribute.getSingleValue(true));
					}
					else {
						query3 = new V(DiagnoserKnowledgeBase.USER, DiagnoserKnowledgeBase.FITS + " " +searchObjectAttribute.getAttributeName().replace("_", " "), defects);
					}
					
					
					if (doIterativeDeepSearch(query3)) {
						isFound = true;
					}
					
					confidence = confidence + (float) query3.getConfidence();
					
				} else {
					ArrayList<String> tempList = searchObjectAttribute.getAttributeValues(true);

					for (String s: tempList) {
						
						counter++;
						V query3 = null;
						
						if (fast) {
							query3 = new V(defects, searchObjectAttribute.getAttributeName().replace("_", " "), s);
						}
						else {
							query3 = new V(DiagnoserKnowledgeBase.USER, DiagnoserKnowledgeBase.FITS + " " +searchObjectAttribute.getAttributeName().replace("_", " "), defects);
						}
						

						if (doIterativeDeepSearch(query3)) {
							isFound = true;
						}
						
						
						confidence = confidence + (float) query3.getConfidence();
						
					}
					
				}
			}
			
			if (isFound) {
				Objects objects = new ObjectsDao().getObjectByMd5(defects);
				if (objects != null) {
					System.out.println("Znalazłem: " + objects.getName());
					possibleDefects.add(new DiagnoserResultDTO(objects.getId(), objects.getName(), confidence / counter));
				}
			}
			
			/*
			 * rozbicie na konkretne cechy szukamy czy cecha pasuje uzytkownikowi
			 */
			/*
			Boolean isFound = false;
			Integer counter = 0;
			Float confidence = new Float(0);
			for(SearchObjectAttribute searchObjectAttribute : searchCriteria) {
				counter++;
				

				if(searchObjectAttribute.isSingle()) {
					
					V query3 = new V(DiagnoserKnowledgeBase.USER, new DiagnoserKnowledgeBase().getFitForAttribute(searchObjectAttribute.getAttributeName().replace("_", " ")), searchObjectAttribute.getSingleValue(true));

					System.out.println(query3);
					System.out.println(doIterativeDeepSearch(query3));
					//if (isFound) {
						if (doIterativeDeepSearch(query3)) {
							isFound = true;
						}
						confidence = confidence + (float) query3.getConfidence();
					//}
				} else {
					ArrayList<String> tempList = searchObjectAttribute.getAttributeValues(true);
					//isFound = false;
					for (String s: tempList) {
						V query3 = new V(DiagnoserKnowledgeBase.USER, new DiagnoserKnowledgeBase().getFitForAttribute(searchObjectAttribute.getAttributeName().replace("_", " ")), s);
						
						
						if (doIterativeDeepSearch(query3)) {
							isFound = true;
						}
						confidence = confidence + (float) query3.getConfidence();
						
					}
					
				}
			}
			
			if (isFound) {
				Objects objects = new ObjectsDao().getObjectByMd5(defects);
				if (objects != null) {
					System.out.println("Znalazłem: " + objects.getName());
					possibleDefects.add(new DiagnoserResultDTO(objects.getId(), objects.getName(), confidence / counter));
				}
			}
			
			/**/
			
		}
		
		Collections.sort(possibleDefects);
		Collections.reverse(possibleDefects);
		return possibleDefects;
	}
	
	@Override
	protected Vertex makeMLRuleVertex(Vertex arg0) {
		return null;
	}

	@Override
	protected boolean runMachineLearning(MLRule arg0) {
		return false;
	}

}
